package com.baidu.aip.demotest;

import com.baidu.aip.talker.controller.Session;
import com.baidu.aip.talker.facade.Controller;
import com.baidu.aip.talker.facade.ISessionController;
import com.baidu.aip.talker.facade.exception.InitException;
import com.baidu.aip.talker.facade.exception.SendException;
import com.baidu.aip.talker.facade.upload.LogBeforeUploadListener;

import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import java.io.*;

public class BiccTest  {
     static AudioRecorder recorder ;
    String file1 = "";

    private int n = 1;
    public int getN() {
        return n;
    }

    public void setN(int n) {
        this.n = n;
    }

    public static void main(String[] args)throws  Exception {


            BiccTest biccTest = new BiccTest();
            biccTest.startAudio();
    }
    public  void startAudio() throws  Exception{
        //Todo
        /*启动 麦克风*/
        recorder = new AudioRecorder();
        System.out.println("请等待程序正常退出， 否则测试用户将导致10分钟内无法正常使用。");
        //String dir = "src/test/resources/pcm";
        Controller controller = new Controller(new LogBeforeUploadListener(), new PrintAfterDownloadListener());
        BiccTest.asrAudio(controller,n);
        controller.stop();//服务停止
    }


    /*
     * @param controller Controller 实例
     * @param file  需要识别的文件
     */
    public static void asrOne(ISessionController controller, String file) {
        // createConfig第一个参数RoleId 三选一：AGENT（仅客服录音） CLIENT (仅客户录音）BOTH（2路录音，见asrBoth）
        // createConfig第二个参数isCompress: 是否需要传输压缩数据，仅linux x64可以开启
        Session.Config config = Session.createConfig(Session.Config.RoleId.AGENT, false);
        // 下面一段为params的设置，仅需要最终识别结果，详细见文档，
        /*
        Map<String, Object> sentenceHandlerParams = new LinkedHashMap<>();
        sentenceHandlerParams.put("agent", "STANDARD_COMPLETED");
        sentenceHandlerParams.put("client", "STANDARD_COMPLETED");
        Map<String, Object> params = new LinkedHashMap<>();
        params.put("sentenceHandler", sentenceHandlerParams);
        config.setParams(params);
        */
        config.setAgentDn(123); // 坐席号, 用户自行定义

        try {

            //初始化session 并发送开始包 config
            Session session = controller.startSession(config);
            registerShutdown(controller, session); // ctrl C 退出时发送end 包
            asr(session, file, true);//读取语音流
            session.sendEndSpeech();//结束会话
            session.destroy();//销毁会话，解除资源占用
        } catch (Exception e) {
            e.printStackTrace();
            System.err.println("meet exception to exit");
            System.exit(5);
        }
    }



    /**
     * 读取语音流添加到 session
     */
    private static void asr(Session session, String file, boolean isFirst) throws Exception {
        FileInputStream stream = null;
        try {
            //读取语音文件流
            stream = new FileInputStream(file);
            int n = 0;//语音文件中读取的到的数据长度，为 0 表示读完了
            int packageDurationInMs = 160;//发送语音间隔ms
            //循环读取语音流
            do {
                try {
                    Thread.sleep(packageDurationInMs);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                byte[] bytes = new byte[packageDurationInMs * 16];//语音流长度
                n = stream.read(bytes);

                if (n > 0) {
                    if (isFirst) {
                        session.sendFirstRoleSpeech(bytes);//把流数据 发送到 session中
                    } else {
                        session.sendSecondRoleSpeech(bytes); // 如果roleId=2 会有第二路通话
                    }
                }
            } while (n > 0);
        } finally {
            if (stream != null) {
                try {
                    stream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }



    /**
     * Audio 获取麦克风 音频流转写
     * @param controller
     *
     */
    public static void asrAudio(ISessionController controller,int n) {
        byte[] bytes = new byte[16];
        System.out.println("asrAudio + bytes:" +bytes.length);
        // createConfig第一个参数RoleId 三选一：AGENT（仅客服录音） CLIENT (仅客户录音）BOTH（2路录音，见asrBoth）
        // createConfig第二个参数isCompress: 是否需要传输压缩数据，仅linux x64可以开启
        Session.Config config = Session.createConfig(Session.Config.RoleId.AGENT, false);
        // 下面一段为params的设置，仅需要最终识别结果，详细见文档，
        /*
        Map<String, Object> sentenceHandlerParams = new LinkedHashMap<>();
        sentenceHandlerParams.put("agent", "STANDARD_COMPLETED");
        sentenceHandlerParams.put("client", "STANDARD_COMPLETED");
        Map<String, Object> params = new LinkedHashMap<>();
        params.put("sentenceHandler", sentenceHandlerParams);
        config.setParams(params);
        */
        config.setAgentDn(123); // 坐席号, 用户自行定义

        try {
            //初始化session 并发送开始包 config
            Session session = controller.startSession(config);
            registerShutdown(controller, session); // ctrl C 退出时发送end 包

            asrSession(session, n, true);//读取语音流


            session.sendEndSpeech();//结束会话
            session.destroy();//销毁会话，解除资源占用
        } catch (Exception e) {
            e.printStackTrace();
            System.err.println("meet exception to exit");
            System.exit(5);
        }
    }
    /**
     * 读取语音流添加到 session
     */
    private static void asrSession1(Session session, String file) throws Exception {
        FileInputStream stream = null;
        try {
            //读取语音文件流
            stream = new FileInputStream(file);
            int n = 0;//语音文件中读取的到的数据长度，为 0 表示读完了
            int packageDurationInMs = 160;//发送语音间隔ms
            //循环读取语音流
            do {
                try {
                    Thread.sleep(packageDurationInMs);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                byte[] bytes = new byte[packageDurationInMs * 16];//语音流长度
                n = stream.read(bytes);

                if (n > 0) {

                        session.sendFirstRoleSpeech(bytes);//把流数据 发送到 session中

                }
            } while (n > 0);
        } finally {
            if (stream != null) {
                try {
                    stream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 麦克风获取音频
     * 读取语音流添加到 session
     * @param session

     * @param isFirst
     * @throws Exception
     */
    private static void asrSession(Session session,int n1, boolean isFirst)  throws Exception {
//        FileInputStream stream = null;
//        ByteArrayOutputStream stream1 ;
        byte[] bytes = new byte[16];
        System.out.println("语音识别已启动");


        AudioFileFormat.Type fileType1 = AudioFileFormat.Type.WAVE;


        try {
//            System.out.println("语音流传输 + asrSession");
            //读取语音文件流
//            stream =
//            new AudioInputStream(recorder.td);
            int m = 0;//语音文件中读取的到的数据长度，为 0 表示读完了
            int packageDurationInMs = 160;//发送语音间隔ms
            //循环读取语音流
            int flag = 0;
            do {
                try {
                    Thread.sleep(packageDurationInMs);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                System.out.println("读取语音流："+ flag);

                recorder.td.open(recorder.audioFormat);
                recorder.td.start();

                recorder.td.getFormat().getEncoding().equals(AudioFormat.Encoding.PCM_FLOAT);
//                System.out.println("编码格式" + recorder.td.getFormat().getEncoding());
                recorder.stream =  AudioSystem.getAudioInputStream(recorder.td.getFormat(),new AudioInputStream(recorder.td));


                    byte []  byte1= new byte[packageDurationInMs * 16];//语音流长度
                    m = recorder.stream.read(byte1);
//                    System.out.println("读取语音流");
                    if (recorder.n > 0 && m>0) {
//                        System.out.println("发送语音流");
                        session.sendFirstRoleSpeech(byte1);//把流数据 发送到 session中
                        flag ++ ;

                    }




            } while (recorder.n > 0);
        } finally {
            System.out.println("BiccTest ：结束");
            if (recorder.stream!= null) {
                recorder.stream.close();
                System.out.println("BiccTest ：recorder.td  stop :麦克风关闭");
            }
        }
    }



    /**
     * 退出时发送end包
     * @param controller
     * @param session
     */
    private static void registerShutdown(ISessionController controller, Session session) {
        Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    session.sendEndSpeech();
                    Thread.currentThread().sleep(1000);
                } catch (SendException e) {
                    e.printStackTrace();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }));
    }



    /**
     * 双通道 客服+用户
     * @param controller
     * @param fileAgent
     * @param fileCustomer
     */
    public static void asrBoth(final ISessionController controller, final String fileAgent, final String fileCustomer) {
        asrBoth(controller, fileAgent, fileCustomer, false);
    }

    /**
     * asrBoth
     * @param controller
     * @param fileAgent
     * @param fileCustomer
     * @param skipExit
     */
    public static void asrBoth(final ISessionController controller, final String fileAgent,
                               final String fileCustomer, boolean skipExit) {
        // createConfig BOTH（2路录音，见asrBoth）
        // createConfig第二个参数isCompress: 是否需要传输压缩数据，仅linux x64可以开启
        final Session.Config config = Session.createConfig(Session.Config.RoleId.BOTH, false);
        try {
            final Session session = controller.startSession(config);
            if (!skipExit) {
                registerShutdown(controller, session);
            }
            Thread th1 = new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        asr(session, fileAgent, true);
                    } catch (Exception e) {
                        e.printStackTrace();
                        System.err.println("Exception caught, exit now");
                        System.exit(5);
                    }
                }
            });
            Thread th2 = new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        asr(session, fileCustomer, false);
                    } catch (Exception e) {
                        e.printStackTrace();
                        System.err.println("meet exception to exit");
                        System.exit(6);
                    }
                }
            });

            th1.start();
            th2.start();

            th1.join();
            th2.join();
            session.sendEndSpeech(); // 必须等坐席客服全部发送完成，才能end。
            session.destroy();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (SendException e) {
            e.printStackTrace();
        } catch (InitException e) {
            e.printStackTrace();
        }
    }

}
